local listener = Cooldowns;

local defaultSettings = {
    userAnchors = {},
    keybindings = {},
    isAnnouncing = true,
    standardSetting = nil,
    displayName = "Cooldowns",
    standardAnnounce = "My cooldown on %s will finish in %d.",
};

function listener:FindAnchor(name, isExternal)
    name = string.lower(name);
    local default, externalLoc;
    for anchor, settings in pairs(self:Get("userAnchors")) do
        if isExternal and settings.externalLoc then
            externalLoc = anchor;
        end
        if settings.timers then
            for entry in pairs(settings.timers) do
                if string.find(name, entry) then
                    return anchor;
                end
            end
        end
        if settings.default then default = anchor; end
    end
    
    return externalLoc or default;
end

function listener:FindTimerSettings(name, anchor)
    name = string.lower(name);
    local settings = self:Get("userAnchors", anchor);
    if settings.timerSettings then
        for setting, entries in pairs(settings.timerSettings) do
            for entry in pairs(entries) do
                if string.find(name, entry) then
                    return setting;
                end
            end
        end
    end
    return self:Get("standardSetting");
end

function listener:MakeTimer(timer)
    --self:Print(string.format("New Cooldown: %s (%f)!", timer.name, timer.duration));
    local anchor = self:FindAnchor(timer.name, timer.module ~= self);
    local timerSettings;
    if timer.module == self then
        timerSettings = self:FindTimerSettings(timer.name, anchor);
    else
        timerSettings = timer.module.GetTimerSettings and timer.module:GetTimerSettings(self, timer.name) or nil;
    end
    local isHidden = timer.module == self and self:Get("blocked", string.lower(timer.name));
    local priority = timer.module == self and 0 or 10;
    local tID = TimerLib:NewTimer(timer, self:Get("displayName"), timer.module, timerSettings, priority, isHidden, anchor, 10, nil);
    --local tID, gID = TimerLib:NewTimer(timer, "Important", timer.module, nil, timer.module == self and 0 or 10, isHidden, "Important Anchor", 10, nil);
    timer.id = tID;
end

function listener:RemoveTimer(timer)
    --self:Print(string.format("Cooldown Done: %s!", timer.name));
    TimerLib:DeleteTimer(timer.id, timer, (timer.module ~= self));
end

function listener:UpdateTimerData(timer)
    --self:Print(string.format("The timer data of %s has changed!", timer.name));
    TimerLib:UpdateTimer(timer.id, timer);
    if timer.nameChanged then
        timer.nameChanged = false;
        self:UpdateAnchor(timer);
    end
end

listener:SetScript("OnTimerEnter", function(self, target, timer, id, frame)
    if not timer then return; end
    local point = "ANCHOR_RIGHT";
    local counter = 5;
    repeat
        local SpellLib = AsheylaLib:GetLibrary("SpellLib");
        target = timer.target;
        Ash_GameTooltip:SetOwner(frame, point);
        Ash_GameTooltip:ClearLines();
        local time = GetTime();
        
        if timer.foundTooltip == nil then
            timer.foundTooltip = false;
            local _, book, index = SpellLib:FindSpellInfo(timer.name, timer.rank, "spell");
            if book and index then
                timer.foundTooltip = true;
                timer.tooltipType = "spell";
                timer.tooltipBook = book;
                timer.tooltipIndex = index;
            else
                local _, _, itemID = SpellLib:FindSpellInfo(timer.name, nil, "item");
                if itemID then
                    timer.foundTooltip = true;
                    timer.tooltipType = "item";
                    timer.tooltipItemID = itemID;
                end
            end
        end
        
        if timer.foundTooltip then
            if timer.tooltipType == "spell" then
                Ash_GameTooltip:SetSpell(timer.tooltipIndex, timer.tooltipBook);
            else
                Ash_GameTooltip:SetHyperlink(SpellLib:ReturnItemLink(timer.tooltipItemID));
            end
            Ash_GameTooltip:AddLine(" ");
        end
        
        Ash_GameTooltip:AddLine(string.format("|cff00ff00%s|r %s", timer.name, timer.rank and "(|cff00ffff" .. timer.rank .. "|r)" or ""));
        Ash_GameTooltip:AddLine("Remaining: |cff6666ff" .. id:FormatTime(timer.duration - time + timer.time));
        
        Ash_GameTooltip:AddLine(" ");
        Ash_GameTooltip:AddLine("|cffffffff" .. listener:GetKeyBinding("Timer", "Announce") .. "|r to announce.");
        Ash_GameTooltip:AddLine("|cffffffff" .. listener:GetKeyBinding("Timer", "Remove") .. "|r to remove.");
        Ash_GameTooltip:AddLine("|cffffffff" .. listener:GetKeyBinding("Timer", "Block") .. "|r to block.");
        
        Ash_GameTooltip:Show();
        if Ash_GameTooltip:GetWidth() >= UIParent:GetRight() - frame:GetRight() then
            if point == "ANCHOR_LEFT" then
                break;
            else
                point = "ANCHOR_LEFT";
            end
        else   
            break;
        end
        counter = counter - 1;
    until counter <= 0;
    if (counter <= 0) then print("CD fail"); end
end)

listener:SetScript("OnTimerLeave", function(self, target, timer, id, frame)
    Ash_GameTooltip:Hide();
end)

listener:SetScript("OnTimerClick",function(self, target, timer, id, button)
    if timer then
        listener:ProcessClick("Timer", button, timer, id);
    else
        TimerLib:DeleteTimer(id, timer, 1);
    end
end)
listener:SetClickAction("Timer", "Remove", function(timer, id)
    TimerLib:DeleteTimer(id, timer, 1);
end)
listener:SetClickAction("Timer", "Block", function(timer)
    if timer then
        local frame = StaticPopup_Show("COOLDOWNS", timer.name)
        frame.data = timer.name;
        frame.data2 = listener;
    end
end)
local subTimer, subID;
local subFunc = function(a)
    if a == "%s" then
        return subTimer.name;
    elseif a == "%d" then
        return subID:FormatTime(subTimer.duration - GetTime() + subTimer.time);
    else
        return "";
    end
end
listener:SetClickAction("Timer", "Announce", function(timer, id)
    if listener:Get("isAnnouncing") then
        local subStr = listener:Get("standardAnnounce");
        subTimer, subID = timer, id;
        local msg = string.gsub(subStr, "(%%%a)", subFunc);
        local loc = GetNumRaidMembers() > 0 and "RAID" or GetNumPartyMembers() > 0 and "PARTY" or "SAY";
        SendChatMessage(msg, loc);
    end
end)
StaticPopupDialogs["COOLDOWNS"] = {
    text = "Are you sure you want to block |cff00ff00%s|r?  This can be undone from the options panel.",
    button1 = "Yes",
    button2 = "No",
    OnAccept = function(self, name, module) module:Set("blocked", string.lower(name), 1); end,
    whileDead = 1,
    hideOnEscape = 1,
    timeout = 0,
}

listener:AddDefaultSettings(defaultSettings);
listener:AddSettingsUpdateScript(function(self)
    if self:GetUserSet("keybindings") == nil then
        self:Set("keybindings", {
    		["Timer"] = {
    			["Announce"] = "1",
    			["Remove"] = "2",
    			["Block"] = "s-2",
    		},
    	});
    end
    if not self:GetUserSet("userAnchors") then
        self:Set("userAnchors", {
            ["Cooldowns Anchor"] = {
                default = true,
                timers = {},
                timerSettings = {},
                externalLoc = true,
            },
        });
    end
    if self:Get("enabled") then
        self:RegisterEvent("COOLDOWNS_NEW_TIMER", self.MakeTimer);
        self:RegisterEvent("COOLDOWNS_DONE_TIMER", self.RemoveTimer);
        self:RegisterEvent("COOLDOWNS_UPDATE_TIMERDATA", self.UpdateTimerData);
        for timer in self:GetCooldownsTarget():GetTimers() do
            self:UpdateAnchor(timer);
        end
    else
        self:UnregisterEvent("COOLDOWNS_NEW_TIMER");
        self:UnregisterEvent("COOLDOWNS_DONE_TIMER");
        self:UnregisterEvent("COOLDOWNS_UPDATE_TIMERDATA");
        TimerLib:DeleteAllTimers(self);
    end
end);

function listener:UpdateAnchor(timer)
    local anchor = self:FindAnchor(timer.name);
    local timerSettings = self:FindTimerSettings(timer.name, anchor);
    local isHidden = timer.module == self and self:Get("blocked", string.lower(timer.name));
    local priority = timer.module == self and 0 or 10;
    TimerLib:UpdateTimerInfo(timer.id, timer, priority, isHidden, timerSettings);
    TimerLib:MoveTimer(timer.id, timer, self:Get("displayName"), anchor, 10, nil);
end

TimerLib:AddSettingsUpdateScript(function(self)
    if not self:GetUserSet("anchorSettings", "Cooldowns Anchor") then
        self:Set("anchorSettings", "Cooldowns Anchor", {defaultTimerSetting = "Cooldowns Timer"});
    end
    if not self:GetUserSet("timerSettings", "Cooldowns Timer") then
        self:Set("timerSettings", "Cooldowns Timer", {});
    end
    
    local default;
    for name, settings in pairs(Cooldowns:Get("userAnchors")) do
        if not self:Get("anchorSettings", name) then
            Cooldowns:Set("userAnchors", name, nil);
        elseif settings.default then
            default = name;
        end
    end
    if not default then
        Cooldowns:Set("userAnchors", "Cooldowns Anchor", "default", true);
    end
end);
